#include <iostream>
#include <string>
#include <map>
#include "../video.hpp"
#include "../../../libpland/lib/plugin.hpp"
#include <unistd.h>
#include <stdlib.h>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

using namespace std;

using namespace pland;

class Decoder : public UserC_Plugin
{
public:
    Decoder();
    ~Decoder();
    void start();
    void stop();
    void load_queues(SharedDQueue front ,SharedDQueue back);
    void setId(int id);
private:
    SharedDQueue front_;
    SharedDQueue back_;
    bool running_;
    int id_;
};


Decoder::Decoder()
{
    running_ = false;
}

Decoder::~Decoder()
{
}

void Decoder::setId(int id)
{
    id_ = id;
}

void Decoder::start()
{
    utill_log("Pluggin Decoder Started ID:" + utill_to_string(id_));
    srand (time(NULL));
    running_ = true;
    while(running_)
    {
        SharedData source = front_->pop();
        if(source->get_header()->tag > PNG_TAG_MAX)
        {
            back_->push(source);
            continue;
        }
        if(isPNG((char*)source->get_data()))
        {
            utill_log("PNG Decoder: " + utill_to_string(id_) + " Frame " + utill_to_string(source->get_header()->sequenceNumber) + " is bad PNG!");
            continue;
        }
        try
        {
            cv::Mat png(1, source->get_header()->size, CV_8U, source->get_data());
            cv::Mat img = imdecode(png, CV_LOAD_IMAGE_GRAYSCALE);
            int size = img.rows*img.cols;
            char *data = new char[size + sizeof(uint32_t)];
            Data_Header * header = new Data_Header;
            ::memcpy(header,source->get_header(), sizeof(Data_Header));
            header->size = size + sizeof(uint32_t);
            switch(header->tag)
            {
            case PNG_TAG_B:
                header->tag = IMG_TAG_B;
                break;
            case PNG_TAG_G:
                header->tag = IMG_TAG_G;
                break;
            case PNG_TAG_R:
                header->tag = IMG_TAG_R;
                break;
            }

            ::memcpy(data, &img.rows,sizeof(uint32_t));
            ::memcpy(data + sizeof(int32_t), img.data, size);
            SharedData next(new Data(data,header));
            back_->push(next);
        }
        catch(cv::Exception &e)
        {
            continue;
        }
    }
}

void Decoder::stop()
{
    running_ = false;
}

void Decoder::load_queues(SharedDQueue front ,SharedDQueue back)
{
    front_  = front;
    back_  = back;
}


extern "C"
{

UserC_Plugin* Core_GetInstance()
{
    return new Decoder();
}

void Core_KillInstance(UserC_Plugin* a)
{
    delete dynamic_cast<Decoder*>(a);
}

}
